﻿using System;
using System.Web.Mvc;
using NUnit.Framework;
using WeBlog.Controllers;
using WeBlog.DataContext;
using WeBlog.Interfaces;
using WeBlog.Models;
using WeBlog.Repositories;
using WeBlog.Services;
using WeBlog.Tests.Helpers;
using WeBlog.Tests.Mocks;

namespace WeBlog.Tests.Controllers {
	[TestFixture]
	public class CommentControllerTests {
        
        private IUnitOfWork _unitOfWork;
	    private IEmailService _emailService;

        [SetUp]
        public void Setup()
        {
            _unitOfWork = new InMemoryUnitOfWork();
            var commentRepository = new CommentRepository(_unitOfWork);
            _emailService = new FakeEmailService();

            var fakePost = new Post { PostId = 1, Title = "Test", Content = "Hi", PublishDate = DateTime.Now };
            var comment = new PostComment { PostCommentId = 1, Content = "foo", Author = "mike", Email = "admin@weblog.com", DateTime = DateTime.Now, Post = fakePost, CommentStatus=CommentStatuses.Pending};
            var comment2 = new PostComment { PostCommentId = 2, Content = "bar", Author = "john", Email = "john@weblog.com", DateTime = DateTime.Now, Post = fakePost, CommentStatus = CommentStatuses.Pending };
            var comment3 = new PostComment { PostCommentId = 3, Content = "bar", Author = "john", Email = "john@weblog.com", DateTime = DateTime.Now, Post = fakePost, CommentStatus = CommentStatuses.Pending };
            var comment4 = new PostComment { PostCommentId = 4, Content = "bar", Author = "john", Email = "john@weblog.com", DateTime = DateTime.Now, Post = fakePost, CommentStatus = CommentStatuses.Pending };

            commentRepository.Add(comment);
            commentRepository.Add(comment2);
            commentRepository.Add(comment3);
            commentRepository.Add(comment4); 
        }

		[Test]
		public void Manage_Action_Should_Return_Valid_Model() {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);
		    controller.SetFakeControllerContext();		    

            //Act
		    var settings = new GridSettings("PublishDate");
            var result = controller.Manage( settings ) as ViewResult;

            //Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(ManageCommentsViewModel),result.ViewData.Model);			
		}

        [Test]
        public void Approve_Action_Should_Set_CommentStatus_To_Approved_When_Input_Is_Valid()
        {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.Approve(1) as JsonResult;

            //Assert
            Assert.IsTrue((result.Data as JsonResponse).Success);
            Assert.IsNotNull(new CommentRepository(_unitOfWork).FindById(1));
            Assert.AreEqual((int)CommentStatuses.Approved, (int)(new CommentRepository(_unitOfWork).FindById(1).CommentStatus));
        }

        [Test]
        public void Approve_Action_Should_Fail_When_Input_Is_Invalid()
        {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.Approve(100) as JsonResult;

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
        }

        [Test]
        public void Delete_Action_Should_Remove_Data_When_Input_Is_Valid()
        {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.Delete(3) as JsonResult;

            //Assert
            Assert.IsTrue((result.Data as JsonResponse).Success);
            Assert.IsNull(new CommentRepository(_unitOfWork).FindById(3));
        }

        /*[Test]
        public void Delete_Action_Should_Fail_When_Input_Is_Invalid()
        {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.Delete(100) as JsonResult;

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
        }*/

        [Test]
        public void Flag_Action_Should_Succeed_When_Input_Is_Valid()
        {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.Flag(1) as JsonResult;

            //Assert
            Assert.IsTrue((result.Data as JsonResponse).Success);
        }
        
        /*[Test]
        public void Flag_Action_Should_Fail_When_Input_Is_Invalid()
        {
            //Arrange
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.Flag(100) as JsonResult;

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
        }*/

        [Test]
        public void UpdateStatus_Action_Should_Update_Status_When_Input_Is_Valid()
        {
            //Arrange
            var keys = new int[] { 1, 2 };
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.UpdateStatus(keys, (int)CommentStatuses.Approved);

            //Assert
            Assert.IsTrue((result.Data as JsonResponse).Success);

            foreach (int id in keys)
            {
                Assert.AreEqual((int)CommentStatuses.Approved, (int)(new CommentRepository(_unitOfWork).FindById(id).CommentStatus));
            }
        }

        [Test]
        public void UpdateStatus_Action_Should_Fail_When_Input_Is_Invalid()
        {
            //Arrange
            var keys = new int[] { 100, 4 };
            var controller = new CommentController(_unitOfWork, _emailService);

            //Act
            var result = controller.UpdateStatus(keys, (int)CommentStatuses.Approved);

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
            Assert.AreNotEqual((int)CommentStatuses.Approved, (int)(new CommentRepository(_unitOfWork).FindById(4).CommentStatus));            
        }
	}
}
